#ifndef PERMUTACIONCPU_H
#define PERMUTACIONCPU_H

// Includes
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <limits.h>

#include <iostream>
#include <string>

#include <ctime>
#include <cstdlib>

//Incluyo la clase global.cu  que contiene las variables y funciones globales
#include "../utils/global.cu"

using namespace std;


/****************** Representacion Permutacion ********************/

/******************* Declaracion de Funciones del Host *************************/
void representacionPermutacionCPU(int *poblacionActualHost, int *nuevaPoblacionHost, float *fitnessActualHost, float *nuevoFitnessHost,int * poblacionActualAcambiar, int *  nuevaPoblacionAcambiar, int * individuosAMigrarHostCPU, MersenneTwister* mt, int iteracion, int tamVectorPoblacion, int tamVectorFitness, int *individuoAMigrarCPUaGPUhost, float* fitnessOrdenadoHostCPU, int* indicesFitnessOrdenadoHostCPU, float* probabilidadRuletaHostCPU, float* fitnessTotalParaRuletaHostCPU, float* mejorFitnessIndividuoCPU, int tamVectorFitnessMejoresIndividuosCPU, int* mejorIndividuoCPU, int tamVectorMejoresIndividuosCPU, float* matrizCostosHost);

void imprimirPermutacionCPU(float* fitnessHost, int tamVectorFitness, int* poblacionHost, int tamVectorPoblacion);
int obtenerMejorIndividuoPermutacion(int nroPoblacion, float* vectorFitness);

/******************* Declaracion de Funciones Global del  ********************/
void inicializarPoblacionPermutacionCPU(int* poblacion, float* fitnessActual, MersenneTwister *mt, int cantCromosomasPoblacion, float* fitnessOrdenadoHostCPU, float* matrizCostosDevice);
void mainKernelPermutacionCPU(int* poblacionActual, int* nuevaPoblacion, float* fitnessActual, float* nuevoFitness, int * poblacionActualAcambiar, int *  nuevaPoblacionAcambiar, int* individuosAMigrar, MersenneTwister *mt, int nroPoblacion, int posActual, int *individuoAMigrarCPUaGPUhost,  float* fitnessOrdenado, int* vectorIndicesFitnessOrdenado, int iteracion, float* probabilidadRuleta, float* fitnessTotalParaRuleta, int* mejorIndividuo, float* mejorFitnessIndividuoCPU, float* matrizCostosHost);

/******************* Declaracion de Funciones internas del  *****************/
void individuosAMigrarRepresentacionPermutacionCPU(float* nuevoFitness, int* nuevaPoblacion, int* individuosAMigrar, int nroPoblacion, int posActual, int *individuoAMigrarCPUaGPUhost);

void asignarProbabilidadRuletaPermutacionCPU(float* fitnessActual, float* probabilidadRuletaPermutacion, float* fitnessTotalParaRuleta,  MersenneTwister *mt, int nroPoblacion, int posActual);

int seleccionPermutacionCPU(float* vectorFitness, MersenneTwister *mt, int ejecutarFuncion, int nroPoblacion, int posActual, float* probabilidadRuleta, int* vectorIndicesFitnessOrdenado);
int seleccionPorRangoPermutacionCPU(int* vectorIndicesFitnessOrdenado, MersenneTwister *mt, int nroPoblacion, int posActual);
int seleccionPorTorneoPermutacionCPU(float* vectorFitness, MersenneTwister *mt, int nroPoblacion, int posActual);
int seleccionRuedaRuletaPermutacionCPU(float* probabilidadRuleta, MersenneTwister *mt, int nroPoblacion, int posActual);

void cruzamientoRepresentacionPermutacionCPU(int* poblacionActual, int* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, MersenneTwister *mt, int ejecutarFuncion, int nroPoblacion, int posActual);
void cruzamientoCromosomaPMX(int* poblacionActual, int* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual);
void cruzamientoCromosomaOX(int* poblacionActual, int* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual);
void cruzamientoCromosomaCX(int* poblacionActual, int* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad,MersenneTwister *mt, int nroPoblacion, int posActual);

void mutacionPermutacionCPU(int* poblacion, float probabilidad, MersenneTwister *mt, int ejecutarFuncion, int nroPoblacion, int posActual);
void mutacionPorIntercambio(int* poblacion, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual);
void mutacionPorInsercionSimple(int* poblacion, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual);
void mutacionPorInversionIVM(int* poblacion, float probabilidad, MersenneTwister *mt, int nroPoblacion, int posActual);

void asignarFitnessPermutacionCPU(int* poblacion, float* vectorFitness, int nroPoblacion, int posActual, float* fitnessOrdenado, float* matrizCostosHost);

void reemplazoPermutacionCPU(int * poblacionActual, int * nuevaPoblacion, int * poblacionActualAcambiar, int * nuevaPoblacionAcambiar, float * fitnessActual, float* nuevoFitness, int ejecutarFuncion, int nroPoblacion, int posActual);
void reemplazoElitistaPermutacionCPU(int* poblacionActual, int* nuevaPoblacion, int* poblacionActualAcambiar, int* nuevaPoblacionAcambiar, float * fitnessActual, float* nuevoFitness, int nroPoblacion, int posActual);

#endif
